// ============================================================================
// Struct and RAII (Resource Acquisition Is Initialization) 测试套件
// ============================================================================
// 测试struct的基本功能、构造函数 init() 和析构函数 drop()
// 使用 assert 进行严格的测试验证

// ============================================================================
// 基本Struct测试
// ============================================================================

type Person struct {
    name String
    age int
    address String
    salery int
}

// ============================================================================
// RAII测试结构体
// ============================================================================

type Database struct {
    host String
    port int
    connected bool
}

type File struct {
    path String
    open bool
}

type Resource struct {
    name String
    allocated bool
}

type Counter struct {
    value int
}


// ============================================================================
// Person实现
// ============================================================================

impl Person {
    // Regular method
    func greet() {
        println("Hello, I'm ", self.name, ", and I'm ", self.age, "years old, and I live in ", self.address, ", salery is ", self.salery)
    }
    
    // Method to change age
    func set_age(new_age int) {
        self.age = new_age
    }
    
    // Getter methods for testing
    func get_name() String {
        return self.name
    }
    
    func get_age() int {
        return self.age
    }
    
    func get_address() String {
        return self.address
    }
    
    func get_salery() int {
        return self.salery
    }
    
    func set_salery(new_salery int) {
        self.salery = new_salery
    }
}


// ============================================================================
// Database实现
// ============================================================================

impl Database {
    func init() {
        println("Database connecting to ", self.host, ":", self.port)
        self.connected = true
        println("Database connected successfully!")
    }
    
    func drop() {
        if self.connected {
            println("Database disconnecting from ", self.host, ":", self.port)
            self.connected = false
            println("Database disconnected!")
        }
    }
    
    func query(sql String) {
        if self.connected {
            println("Executing query: ", sql)
        } else {
            println("Database not connected!")
        }
    }
    
    func is_connected() bool {
        return self.connected
    }
}

// ============================================================================
// File实现
// ============================================================================

impl File {
    func init() {
        println("Opening file: ", self.path)
        self.open = true
        println("File opened successfully!")
    }
    
    func drop() {
        if self.open {
            println("Closing file: ", self.path)
            self.open = false
            println("File closed!")
        }
    }
    
    func read() {
        if self.open {
            println("Reading from file: ", self.path)
        } else {
            println("File not open!")
        }
    }
    
    func is_open() bool {
        return self.open
    }
}

// ============================================================================
// Resource实现
// ============================================================================

impl Resource {
    func init() {
        println("Resource allocated: ", self.name)
        self.allocated = true
    }
    
    func drop() {
        if self.allocated {
            println("Resource freed: ", self.name)
            self.allocated = false
        }
    }
    
    func use() {
        if self.allocated {
            println("Using resource: ", self.name)
        } else {
            println("Resource not allocated!")
        }
    }
    
    func is_allocated() bool {
        return self.allocated
    }
}

// ============================================================================
// Counter实现（测试字段修改）
// ============================================================================

impl Counter {
    func init() {
        println("Counter initialized with value: ", self.value)
        self.value = self.value * 2  // 修改字段值
        println("Counter value modified to: ", self.value)
    }
    
    func drop() {
        println("Counter destroyed, final value was: ", self.value)
    }
    
    func get_value() int {
        return self.value
    }
}

func test_struct_basic() {
    println("=== Basic Struct Tests ===")
    
    // Test 1: Constructor and initial values
    println("\n--- Test 1: Constructor and Initial Values ---")
    var person Person = Person {
       name: "Alice",
       age: 25, 
       address: "street 1",
       salery: 10000,
    }
    
    // Assert initial values
    assert(person.get_age() == 25, "Age should be 25")
    assert(person.get_salery() == 10000, "Salery should be 10000")
    println("✓ All initial values are correct")
    
    // Test 2: Method call and field modification
    println("\n--- Test 2: Method Call and Field Modification ---")
    person.set_age(26)
    assert(person.get_age() == 26, "Age should be 26 after set_age(26)")
    println("✓ Age successfully changed to 26")
    
    // Test 3: Multiple modifications
    println("\n--- Test 3: Multiple Modifications ---")
    person.set_age(27)
    assert(person.get_age() == 27, "Age should be 27 after set_age(27)")
    println("✓ Age successfully changed to 27")
    
    // Test 4: Verify other fields remain unchanged
    println("\n--- Test 4: Other Fields Remain Unchanged ---")
    assert(person.get_salery() == 10000, "Salery should still be 10000")
    println("✓ Other fields remain unchanged")
    
    // Test 5: Final state verification
    println("\n--- Test 5: Final State Verification ---")
    person.greet()
    assert(person.get_age() == 27, "Final age should be 27")
    assert(person.get_salery() == 10000, "Final salery should be 10000")
    println("✓ Final state verification passed")
}
    
func test_raii_basic() {
    println("=== RAII Tests ===")
    
    // Test 1: 基本构造函数和析构函数
    println("\n--- RAII Test 1: Basic Constructor/Destructor ---")
    var resource Resource = Resource{
        name: "Person Object"
    }
    // 验证对象状态
    assert(resource.is_allocated(), "Resource should be allocated after init")
    resource.use()
}

func test_raii_field_modification() {
    // Test 2: 字段修改测试
    println("\n--- RAII Test 2: Field Modification ---")
    var counter Counter = Counter{
        value: 42
    }
    // 验证字段修改生效
    assert(counter.get_value() == 84, "Counter value should be modified to 84")
    println("Counter value after init: ", counter.get_value())
}

func test_raii_database() {
    // Test 3: Database 对象
    println("\n--- RAII Test 3: Database Object ---")
    var db Database = Database{
        host: "localhost",
        port: 5432
    }
    // 验证Database状态
    assert(db.is_connected(), "Database should be connected after init")
    db.query("SELECT * FROM users")
}

func test_raii_file() {
    // Test 4: File 对象
    println("\n--- RAII Test 4: File Object ---")
    var file File = File{
        path: "/tmp/test.txt"
    }
    // 验证File状态
    assert(file.is_open(), "File should be open after init")
    file.read()
}

func test_raii_multiple_objects() {
    // Test 5: 多对象测试（验证LIFO析构顺序）
    println("\n--- RAII Test 5: Multiple Objects (LIFO Order) ---")
    var res1 Resource = Resource{
        name: "Resource 1"
    }
    assert(res1.is_allocated(), "Resource 1 should be allocated")
    
    var res2 Resource = Resource{
        name: "Resource 2"
    }
    assert(res2.is_allocated(), "Resource 2 should be allocated")
    
    var res3 Resource = Resource{
        name: "Resource 3"
    }
    assert(res3.is_allocated(), "Resource 3 should be allocated")
}

func test_raii_complex_combination() {
    // Test 6: 复杂对象组合
    println("\n--- RAII Test 6: Complex Object Combination ---")
    var db2 Database = Database{
        host: "remote-server",
        port: 3306
    }
    assert(db2.is_connected(), "Database 2 should be connected")
    
    var file2 File = File{
        path: "/var/log/app.log"
    }
    assert(file2.is_open(), "File 2 should be open")
    
    db2.query("SELECT COUNT(*) FROM logs")
    file2.read()
}

func test_reference_basic() {
    // Test 1: Basic reference operations
    println("--- Test 1: Basic Reference Operations ---")
    var a int = 10
    var b int = 20
    var ref_a &int = &a
    
    // Test initial values
    assert(a == 10, "Initial value of a should be 10")
    assert(b == 20, "Initial value of b should be 20")
    assert(ref_a == 10, "Initial value of ref_a should be 10")
    
    // Test value assignment
    ref_a = 30
    assert(a == 30, "After ref_a = 30, a should be 30")
    assert(ref_a == 30, "After ref_a = 30, ref_a should be 30")
    assert(b == 20, "After ref_a = 30, b should still be 20")
    
    // Test reference reassignment
    ref_a = &b
    assert(a == 30, "After ref_a = &b, a should still be 30")
    assert(b == 20, "After ref_a = &b, b should still be 20")
    assert(ref_a == 20, "After ref_a = &b, ref_a should be 20")
    
    // Test value assignment through new reference
    ref_a = 40
    assert(a == 30, "After ref_a = 40, a should still be 30")
    assert(b == 40, "After ref_a = 40, b should be 40")
    assert(ref_a == 40, "After ref_a = 40, ref_a should be 40")
    
    var x int = 100
    var y int = 200
    var z int = 300
    
    var ref1 &int = &x
    var ref2 &int = &y
    var ref3 &int = &z
    
    // Test initial values
    assert(x == 100, "Initial value of x should be 100")
    assert(y == 200, "Initial value of y should be 200")
    assert(z == 300, "Initial value of z should be 300")
    assert(ref1 == 100, "Initial value of ref1 should be 100")
    assert(ref2 == 200, "Initial value of ref2 should be 200")
    assert(ref3 == 300, "Initial value of ref3 should be 300")
    
    // Test chain reassignments
    ref1 = &y
    ref2 = &z
    ref3 = &x
    
    // After reassignments, original variables should be unchanged
    assert(x == 100, "After reassignments, x should still be 100")
    assert(y == 200, "After reassignments, y should still be 200")
    assert(z == 300, "After reassignments, z should still be 300")
    
    // References should now point to different variables
    assert(ref1 == 200, "After ref1 = &y, ref1 should be 200")
    assert(ref2 == 300, "After ref2 = &z, ref2 should be 300")
    assert(ref3 == 100, "After ref3 = &x, ref3 should be 100")
    
    // Test modifications through references
    ref1 = 400
    ref2 = 500
    ref3 = 600
    
    // Test that modifications affect the correct variables
    assert(x == 600, "After ref3 = 600, x should be 600")
    assert(y == 400, "After ref1 = 400, y should be 400")
    assert(z == 500, "After ref2 = 500, z should be 500")
    assert(ref1 == 400, "After ref1 = 400, ref1 should be 400")
    assert(ref2 == 500, "After ref2 = 500, ref2 should be 500")
    assert(ref3 == 600, "After ref3 = 600, ref3 should be 600")
}

func test_reference_complex() {
    // Test 3: Complex reference operations
    println("--- Test 3: Complex Reference Operations ---")
    var original int = 1000
    var ref_to_original &int = &original
    
    // Test initial values
    assert(original == 1000, "Initial value of original should be 1000")
    assert(ref_to_original == 1000, "Initial value of ref_to_original should be 1000")
    
    // Test modification through reference
    ref_to_original = 2000
    assert(original == 2000, "After ref_to_original = 2000, original should be 2000")
    assert(ref_to_original == 2000, "After ref_to_original = 2000, ref_to_original should be 2000")
    
    // Test reference reassignment to point to another variable
    var another int = 3000
    ref_to_original = &another
    assert(original == 2000, "After ref_to_original = &another, original should still be 2000")
    assert(another == 3000, "After ref_to_original = &another, another should still be 3000")
    assert(ref_to_original == 3000, "After ref_to_original = &another, ref_to_original should be 3000")
    
    // Test modification through reassigned reference
    ref_to_original = 4000
    assert(original == 2000, "After ref_to_original = 4000, original should still be 2000")
    assert(another == 4000, "After ref_to_original = 4000, another should be 4000")
    assert(ref_to_original == 4000, "After ref_to_original = 4000, ref_to_original should be 4000")
    
    // Test 4: Reference with struct fields (暂时跳过，因为结构体引用有已知问题)
    println("--- Test 4: Reference with Struct Fields (Skipped) ---")
    println("Note: Reference to struct functionality has known issues and is skipped for now.")
    println("Basic type references work correctly, but struct references need further implementation.")
    
    println("=== All Reference Tests Passed! ===")
}

func test_reference_multiple() {
    // Test 2: Multiple references
    println("--- Test 2: Multiple References ---")
    var a int = 10
    var b int = 20
    var c int = 30
    
    var ref1 &int = &a
    var ref2 &int = &b
    var ref3 &int = &c
    
    // Test initial values
    assert(a == 10, "Initial value of a should be 10")
    assert(b == 20, "Initial value of b should be 20")
    assert(c == 30, "Initial value of c should be 30")
    assert(ref1 == 10, "Initial value of ref1 should be 10")
    assert(ref2 == 20, "Initial value of ref2 should be 20")
    assert(ref3 == 30, "Initial value of ref3 should be 30")
    
    // Test modifications through references
    ref1 = 100
    ref2 = 200
    ref3 = 300
    
    assert(a == 100, "After ref1 = 100, a should be 100")
    assert(b == 200, "After ref2 = 200, b should be 200")
    assert(c == 300, "After ref3 = 300, c should be 300")
    assert(ref1 == 100, "After ref1 = 100, ref1 should be 100")
    assert(ref2 == 200, "After ref2 = 200, ref2 should be 200")
    assert(ref3 == 300, "After ref3 = 300, ref3 should be 300")
    
    println("=== All Multiple Reference Tests Passed! ===")
}

func test_reference_struct_fields_skipped() {
    // Test: Reference with struct fields (暂时跳过，因为结构体引用有已知问题)
    println("--- Test: Reference with Struct Fields (Skipped) ---")
    println("Note: Reference to struct functionality has known issues and is skipped for now.")
    println("Basic type references work correctly, but struct references need further implementation.")
}
